home *** CD-ROM | disk | FTP | other *** search
- page 64,132
- ;========================================================================
- ; SPRINTER
- ; Cursor Speedup Program
- ; Written 1992 by Douglas Boling
- ;========================================================================
- ;========================================================================
- ; BIOS_DATA segment
- ;========================================================================
- bios_data segment at 40h
-
- org 17h
- bios_shift_stat db ? ;Shift status of keyboard
- org 1ah
- keybuff_head dw ? ;Pointer to first entry in
- org 1ch ; BIOS keyboard buffer.
- keybuff_tail dw ? ;Pointer to last entry in
- org 80h ; BIOS keyboard buffer.
- keybuff_start dw ? ;Pointer to beginning of
- org 82h ; BIOS keyboard buffer.
- keybuff_end dw ? ;Pointer to end of BIOS
- org 96h ; keyboard buffer.
- kb_status db ? ;Status of keyboard
- bios_data ends
-
- ;========================================================================
- ; Code segment (code and data)
- ;========================================================================
- code segment para public'code'
- assume cs:code
-
- org 2ch
- env_seg dw ? ;Pointer to environment seg
- org 80h
- command_tail db ?
- org 100h
- begin: jmp initialize
-
- program db 13,10,"Sprinter 1.0 "
- copyright db "Copyright (c) 1992 Douglas Boling",13,10
- db "First published in PC Magazine, May 26, 1992",13,10
- db "For help type: sprinter /?",13,10
- db 13,10,"$",1Ah
-
- ;------------------------------------------------------------------------
- ; Memory locations required for program.
- ;------------------------------------------------------------------------
- enable_flag db 1 ;1 = enabled, 0 = disabled
- shift_status db 0 ;bits represent shift status
- last_code db 0 ;Previous scan code
- cursor_code dw 0 ;Cursor code currently active
- shift_mask db 11h ;Activate using Alt keys
- make_kept db 0 ;key not passed to BIOS
- key_count db 2 ;Number of keys pushed/int
-
- scanlist_ptr label dword ;Pointer to list of scan codes
- dw offset scanlist ;Offset
- dw ? ;Segment
- scanlist db 48h,4bh,4dh,50h,49h,51h ;Cursor key scancodes
- shiftlist db 38h,1dh,2ah,36h ;Alt, Ctl, and L/R shift codes
- scanlist_end = $
-
- environment_flg db 1 ;1 = environment still owned
- int8h dd ? ;int 8h vector (Timer)
- int9h dd ? ;int 9h vector (Keyboard)
-
- ;========================================================================
- ; TIMERINT receives control when an interrupt 8 is generated.
- ;========================================================================
- timerint proc far
- assume cs:code,ds:nothing,es:nothing
- pushf
- call cs:[int8h] ;Go to BIOS routine
- cmp cs:enable_flag,0 ;See if program enabled
- je timer_exit1 ;No, exit
- push ax
- mov al,cs:shift_status ;See if shift combination
- mov ah,cs:shift_mask
- test al,ah
- je timer_exit ;No, exit
- not ah ;See if any other shift key
- and al,ah ; is active.
-
- mov ax,cs:cursor_code ;Get saved cursor key code
- or ax,ax ;See if cursor key active
- je timer_exit ;No, exit
- ;------------------------------------------------------------------------
- ;If shift combination set and cursor key pressed, put scancode into buffer.
- ;------------------------------------------------------------------------
- push ds ;Yes, Save registers needed
- push bx ; for keyboard buffer work.
- push cx
- push di
- mov bx,40h ;DS = BIOS data segment
- mov ds,bx
- assume ds:bios_data
- cli ;No ints when loading buffer
- mov bx,keybuff_tail ;Get pointer to end of buffer
- mov di,bx ;Copy to see if buffer full
- xor ch,ch
- mov cl,cs:key_count ;Get num of keys to push
- timer0:
- call advance_keyptr ;Check ahead in buffer.
- jc timer1 ;If full, goto end
- mov [bx],ax ;Put character in queue
- mov bx,di ;Update pointer
- loop timer0
- timer1:
- mov keybuff_tail,bx ;Save updated keyboard ptr
- sti ;Allow interrupts
- pop di ;Restore registers
- pop cx
- pop bx
- pop ds
- timer_exit:
- pop ax
- timer_exit1:
- iret ;Return
- timerint endp
-
- ;========================================================================
- ; KEYBINT receives control when an interrupt 9 is generated.
- ;========================================================================
- keybint proc far
- assume cs:code,ds:nothing,es:nothing
- push ax
- cmp cs:enable_flag,0 ;See if enabled. If not jump
- je go_kb_int1 ; directly to BIOS.
- in al,64h ;Read keyboard status port.
- test al,1 ;See if output buffer full.
- je go_kb_int1 ;No, must be some other I/O.
- push cx
- push di
- push ds
- mov ax,cs
- mov ds,ax ;DS = CS
- assume ds:code
- in al,60h ;Read keyboard data port.
- sti ;Enable interrupts
- ;------------------------------------------------------------------------
- ;Compare scan code with list of keys.
- ;------------------------------------------------------------------------
- push es
- les di,scanlist_ptr ;Point to list of scan codes.
- mov cx,offset scanlist_end - offset scanlist
- mov ah,al ;Copy scan code
- and al,7fh ;Remove break bit from code
- cld
- repne scasb ;Scan list
- pop es
- jne go_kb_int ;Scancode not in list go BIOS
- sub cx,offset scanlist_end - offset scanlist
- neg cx ;Make positive
- sub cl,offset shiftlist - offset scanlist + 1
- jb cursorkey_found ;If first 6 codes, cursor code
- ;------------------------------------------------------------------------
- ;Shift key scancode. Set or clear bit in shift status.
- ;------------------------------------------------------------------------
- cmp last_code,0e0h ;See if extended code
- jne shiftkey1 ;If extended, increase shift
- add cl,4 ; for right alt or ctl keys.
- shiftkey1:
- mov al,1 ;Use al as a bit set register
- shl al,cl ;Shift bit by index into list
- test ah,80h ;See if make or break code
- jne shiftkey_break ;Break, jump.
- or shift_status,al ;Make, set bit in shift status
- jmp short go_kb_chk ;Goto BIOS
- shiftkey_break:
- push ax
- not al ;Invert mask to clear bit
- and shift_status,al ;Clear bit
- pop ax
- ;------------------------------------------------------------------------
- ;If proper accelerator shift key, don't pass key to BIOS
- ;------------------------------------------------------------------------
- go_kb_chk:
- test al,shift_mask ;If this is the proper
- je go_kb_int ; shift and a cursor key
- cmp cursor_code,0 ; is down, don't pass scan
- je go_kb_int ; code to BIOS.
- test ah,80h ;See if make or break
- jne go_kb_chk1
- mov make_kept,1 ;Indicate make code kept
-
- jmp short go_kb_int
-
- jmp short keyb_iret
- go_kb_chk1:
- mov make_kept,0 ;Clear flag.
- ;------------------------------------------------------------------------
- ;Exit to BIOS keyboard interrupt routine.
- ;------------------------------------------------------------------------
- go_kb_int:
- mov last_code,ah ;Save current code
- pop ds ;Restore registers
- pop di
- pop cx
- go_kb_int1:
- pop ax
- jmp cs:[int9h] ;Go to BIOS routine
- ;------------------------------------------------------------------------
- ;Discard key. Reset the keyboard and signal end-of-interrupt to the 8259
- ;------------------------------------------------------------------------
- keyb_iret:
- call reset_keyboard ;Reset keyboard
- mov last_code,ah ;Save current code
- pop ds ;Restore registers
- pop di
- pop cx
- pop ax
- iret ;Return to program
- ;------------------------------------------------------------------------
- ;Cursor key scancode, check for extended key or number key and numlock on.
- ;------------------------------------------------------------------------
- cursorkey_found:
- xor al,al ;Assume 0 extended scancode
- cmp last_code,0e0h ;See if extended key
- jne cursorkey_numpad
- mov al,0e0h ;Load extended keycode.
- jmp short cursorkey1
- cursorkey_numpad:
- push es
- push ax
- mov ax,40h ;ES = BIOS data segment
- mov es,ax
- assume es:bios_data
- pop ax
- test es:bios_shift_stat,20h ;See if numlock active
- pop es
- assume es:nothing
- jne go_kb_int ;If so, not a cursor key.
- ;------------------------------------------------------------------------
- ;Check for break code. If break, clear stored scan code.
- ;------------------------------------------------------------------------
- cursorkey1:
- test ah,80h ;See if break
- je cursorkey_make ;No, continue
- xor ax,ax ;Yes, clear last code
- cursorkey_make:
- mov cursor_code,ax ;Save cursor code
-
- mov al,shift_status ;See if shift combination
- test shift_mask,al
- jne keyb_iret
-
- jmp go_kb_int ;Yes, goto BIOS
- keybint endp
-
- ;========================================================================
- ; ADVANCE KEYPTR moves the keyboard buffer pointer to the next free
- ; location in the BIOS keyboard buffer.
- ; Entry: DI - keyboard head pointer
- ; Exit: CF - Set if keyboard buffer full
- ;========================================================================
- advance_keyptr proc near
- assume cs:code,ds:bios_data
- inc di ;Point to next entry
- inc di
- cmp di,keybuff_end ;See if at the end of the
- jne advance1 ; buffer. If so, reset the
- mov di,keybuff_start ; pointer to the start.
- advance1:
- cmp di,keybuff_head ;See if the buffer is full
- je advance_full
- clc
- jmp short advance_exit
- advance_full:
- stc
- advance_exit:
- ret
- advance_keyptr endp
-
- ;========================================================================
- ; RESET KEYBOARD resets the interrupts controller. Used when discarding
- ; scan codes.
- ;========================================================================
- reset_keyboard proc near
- push ax
- cli ;Disable interrupts
- in al,61h ;Reset the keyboard
- mov ah,al ; controller
- or al,80h
- out 61h,al
- mov al,ah
- out 61h,al
-
- mov al,20h ;Signal end-of-interrupt to
- out 20h,al ; the interrupt controller
- sti ;Enable interrupts
- pop ax
- ret
- reset_keyboard endp
- end_of_code = $
- ;========================================================================
- ; End of nonresident code.
- ;========================================================================
- infomsg1 db "The available commands are:"
- db 13,10,"/e Enable acceleration"
- db 13,10,"/d Disable acceleration"
- db 13,10,"/u Uninstall program"
- db 13,10,"/s x Set acceleration speed where x"
- db " is between 1 and 9"
- db 13,10,"/k xx Set shift key where xx is one of"
- db " the following:"
- db 13,10," a Alt key"
- db 13,10," c Ctl key"
- db 13,10," s Shift key"
- db 13,10," lx to specify only the left key"
- db 13,10," rx to specify only the right key"
- db 13,10,"/? Print this message$"
- infomsg2 db "Sprinter removed$"
- infomsg3 db "Sprinter installed",13,10,"$"
- infomsg4 db "Acceleration key is "
- keytag db 15 dup (" "),13,10
- db "Acceleration speed is "
- speedtag db 2 dup (" "),13,10,10,"$"
- errmsg1 db "Bad commmand$"
- errmsg2 db "Can't remove$"
- errmsg3 db "Bad shift key$"
- errmsg4 db "Not installed$"
- errmsg5 db "Bad key speed$"
- end_msg db 13,10,"$"
-
- left_tag db "<Left>",0
- right_tag db "<Right>",0
- alt_tag db "<Alt>",0
- ctrl_tag db "<Ctrl>",0
- shift_tag db "<Shift>",0
-
- commands db 'edksu?' ;Letters corrsponding to the
- commands_end = $ ; command line switches.
-
- jumptable:
- dw offset enable ;Command routine jump table
- dw offset disable
- dw offset keyset
- dw offset speedset
- dw offset uninstall
- dw offset display_help
-
- shiftkeys db 'lracs' ;Letters corrsponding to the
- shiftkeys_end = $ ; shift keys allowed.
-
- other_seg dw 0 ;Segment of installed code
- alrdy_installed db 0 ;bcopy already installed flag
- remove_flag db 0 ;1 = uninstall
-
- ;========================================================================
- ; INITIALIZE
- ;========================================================================
- initialize proc near
- assume cs:code, ds:code
- cld ;clear DF
- mov ah,9 ;display copyright message
- mov dx,offset program
- int 21h
- ;------------------------------------------------------------------------
- ;See if a copy is already resident in memory.
- ;------------------------------------------------------------------------
- mov word ptr [begin],0 ;initialize fingerprint
- mov bx,0a000h ;Start at UMBs
- mov ax,cs ;keep CS value in AX
- find_copy:
- inc bx ;increment search segment value
- mov es,bx
- cmp ax,bx ;not installed if current
- je find_copy1 ; segment is looped back to
- mov si,offset begin ;search this segment for ASCII
- mov di,si ; fingerprint
- mov cx,16
- repe cmpsb
- jne find_copy ;loop back if not found
- inc alrdy_installed ;Clear installed flag
- find_copy1:
- mov other_seg,es ;save installed code segment
- push cs ;ES = CS
- pop es
- assume es:code
- ;------------------------------------------------------------------------
- ;Parse the command line for switches.
- ;------------------------------------------------------------------------
- mov si,offset command_tail ;point SI to command line text
- xor cx,cx ;Clear high byte of CX
- add cl,[si] ;Get length of command line.
- jz parse_line_end ;If zero, skip parse routine
- inc si
- parse_line_loop:
- lodsb ;Get byte
- cmp al,'/' ;Look for command switch
- je parse_line_skip ;If found, process command
- loop parse_line_loop ;If not, keep looking
- jmp short parse_line_end
- parse_line_skip:
- lodsb ;Get command
- or al,20h ;Convert to lower case
- push cx
- mov di,offset commands ;Point to command letters
- mov cx,offset commands_end - offset commands
- mov bx,cx ;Save number of routines
- repne scasb ;Find command letter
- je command_found
- add sp,2 ;Clean up stack
- mov dx,offset errmsg1 ;Command not found msg
- jmp short disp_error
- command_found:
- sub bx,cx ;Compute offset into table
- pop cx ;Get back character count
- dec bx
- shl bx,1 ;Convert to word
- push es
- call [bx+offset jumptable]
- pop es
- jc disp_error ;Error if carry set.
- loop parse_line_loop
- parse_line_end:
- ;------------------------------------------------------------------------
- ;Construct and print Accel key message
- ;------------------------------------------------------------------------
- mov di,offset keytag
- mov es,other_seg
- mov al,es:shift_mask ;Get shift key
- mov ah,es:key_count ;Get key speed
- push ax ;Save key speed value
- push cs
- pop es
- mov bl,al ;See if specific to left
- mov cl,4 ; or right keys.
- shr bl,cl
- test al,8
- je accel_0
- or bl,4
- accel_0:
- and al,07h
- cmp al,bl ;Compare left and right
- je accel_2 ; masks.
- mov si,offset left_tag
- ja accel_1
- mov si,offset right_tag
- accel_1:
- call copy_str ;Copy Left/Right tag
- accel_2:
- or al,bl
- mov si,offset alt_tag
- test al,1
- jne accel_3
- mov si,offset ctrl_tag
- test al,2
- jne accel_3
- mov si,offset shift_tag
- accel_3:
- call copy_str
- pop ax ;Insert key speed value in
- add ah,30h ; message
- mov speedtag,ah
-
- mov ah,9 ;Print message
- mov dx,offset infomsg4
- int 21h
-
- ;------------------------------------------------------------------------
- ;See if installed. If not, install.
- ;------------------------------------------------------------------------
- cmp alrdy_installed,0 ;If not installed, install
- je install
- mov ax,4c00h ;Else, terminate with RC = 0.
- int 21h
-
- ;------------------------------------------------------------------------
- ;Display error message and exit with Return Code = 1.
- ;------------------------------------------------------------------------
- disp_error:
- mov ah,9 ;Print string
- int 21h
- mov dx,offset end_msg
- mov ah,9 ;Print CR,LF
- int 21h
- mov ax,4c01h ;Exit RC = 1
- int 21h
-
- ;------------------------------------------------------------------------
- ;Install. Revector interrupts, Terminate and Stay Resident.
- ;------------------------------------------------------------------------
- install:
- mov ax,cs ;Copy code segment
- mov word ptr [scanlist_ptr+2],ax ;Load segment into ptr
- mov ax,3508h ;Set interrupt 8 (timer)
- int 21h ; to the internal handler.
- mov word ptr [int8h],bx
- mov word ptr [int8h+2],es
- mov ax,2508h
- mov dx,offset timerint
- int 21h
- mov ax,3509h ;Set interrupt 9 (keyboard)
- int 21h ; to the internal handler.
- mov word ptr [int9h],bx
- mov word ptr [int9h+2],es
- mov ax,2509h
- mov dx,offset keybint
- int 21h
- mov dx,offset infomsg3 ;Say program installed.
- mov ah,9h
- int 21h
- mov dx,offset end_of_code ;Get pointer to the end of
- add dx,15 ; code.
- mov cl,4
- shr dx,cl ;Convert to paragraphs
- mov ax,3100h ;terminate with ERRORLEVEL = 0
- int 21h ;Return to DOS.
- initialize endp
-
- ;------------------------------------------------------------------------
- ; ENABLE activates the cursor speedup feature.
- ;------------------------------------------------------------------------
- enable proc near
- assume cs:code,ds:code
- mov es,other_seg ;point to installed segment
- mov es:enable_flag,1 ;Set enable flag
- clc
- ret
- enable endp
-
- ;------------------------------------------------------------------------
- ; DISABLE deactivates the cursor speedup feature.
- ;------------------------------------------------------------------------
- disable proc near
- assume cs:code,ds:code
- mov es,other_seg ;point to installed segment
- mov es:enable_flag,0 ;Clear enable flag
- clc
- ret
- disable endp
-
- ;------------------------------------------------------------------------
- ; SPEEDSET sets the number of keys pushed into the buffer per timer int
- ;------------------------------------------------------------------------
- speedset proc near
- assume cs:code,ds:code
- speedset_loop:
- jcxz speedset_err ;If EOL, error.
- lodsb
- dec cx
- cmp al," "
- jbe speedset_loop
- sub al,30h ;Convert to hex
- jbe speedset_err
- cmp al,9
- ja speedset_err
- mov es,other_seg ;Get seg of installed code
- mov es:key_count,al ;Set count
- clc
- speedset_exit:
- ret
- speedset_err:
- mov dx,offset errmsg5 ;Bad key speed message
- stc
- jmp short speedset_exit
- speedset endp
-
- ;------------------------------------------------------------------------
- ; KEYSET sets the shift key for acceleration of the cursor.
- ;------------------------------------------------------------------------
- keyset proc near
- assume cs:code,ds:code
- mov dx,003fh ;Use DX as shift bit mask
- keyset_loop:
- mov al,[si] ;Get byte
- cmp al,'/' ;If next switch, end.
- je keyset_end
- inc si
- cmp al,' ' ;Check for a space.
- jb keyset_end ;If non character, exit
- ja keyset0 ;If not a space, process.
- loop keyset_loop ;If at the end of the command
- jmp short keyset5 ; line, end.
- keyset0:
- or al,20h ;Convert to lower case
- mov di,offset shiftkeys ;Point to command letters
- push cx ;Save command line count
- mov cx,offset shiftkeys_end - offset shiftkeys
- mov bx,cx ;Save number of keys
- repne scasb ;Find shift key letter
- je shiftkey_found ;If found, continue.
- add sp,2 ;If not, Clean up stack.
- mov dx,offset errmsg3 ;Not a proper shift key msg
- stc ;Set carry and exit.
- jmp short keyset_exit
- shiftkey_found:
- sub bx,cx ;Create index into keylist
- dec bx ;Check for left and right
- cmp bl,1 ;qualifiers, if so fix mask.
- ja keyset2 ;Not left or right, continue
- jb keyset1 ;Check for left qualifier
- and dl,38h ;Right qualifier, Clear off
- jmp short keyset4 ; left shift bits.
- keyset1:
- and dl,07h ;Left qualifier, Clear off
- jmp short keyset4 ; right shift bits.
- keyset2:
- mov cl,bl ;Shift bits by the index into
- sub cl,2 ; list of keys. This creates
- mov bl,11h ; a mask compatible with the
- shl bl,cl ; shift mask used in the int
- cmp bl,44h ; routine.
- jne keyset3 ;Fix mask if shift key
- mov bl,0ch
- keyset3:
- and bl,dl ;Clear off bits for L/R
- or dh,bl ;Add to shift mask
- mov dl,3fh ;Reset left/right mask
- keyset4:
- pop cx ;Restore command line counter
- loop keyset_loop ;Loop if not EOL
- keyset5:
- inc cx ;Fool loop instruction on ret
- keyset_end:
- or dh,dh ;Check for nul shift mask
- jne keyset6 ;If zero, set unshiftable bit
- mov dh,80h ; to disable.
- keyset6:
- mov es,other_seg ;point to installed segment
- mov es:shift_mask,dh ;Set new shift mask
- clc
- keyset_exit:
- ret
- keyset endp
-
- ;------------------------------------------------------------------------
- ; DISPLAY HELP prints help message without installing.
- ;------------------------------------------------------------------------
- display_help proc near
- mov dx,offset infomsg1 ;point to help text.
- stc ;Set flag to print message.
- ret
- display_help endp
-
- ;------------------------------------------------------------------------
- ; UNINSTALL deallocates the memory block ownded by the program and
- ; restores the interrupt vectors displaced on installation.
- ;------------------------------------------------------------------------
- uninstall proc near
- assume cs:code,ds:code
- push cx ;Save command line count
- cmp alrdy_installed,0 ;If not installed, don't
- jne uninstall0 ; remove.
- mov dx,offset errmsg4 ;Not installed msg
- jmp short uninstall_exit
- uninstall0:
- mov cx,other_seg ;Get segment of installed prog
- ;
- ;Make sure the timer and keyboard vectors has not been altered.
- ;
- mov ax,3508h ;check interrupt 8h vector
- int 21h
- mov ax,es
- cmp cx,ax ;transfer segment to AX
- jne uninstall_error
- mov ax,3509h ;check interrupt 9h vector
- int 21h
- mov ax,es
- cmp cx,ax ;transfer segment to AX
- jne uninstall_error
- ;
- ;Restore interrupt 8 and 9 vectors.
- ;
- mov es,cx ;Copy installed segment
- push ds ;save DS
- assume ds:nothing
- lds dx,es:[int8h]
- mov ax,2508h ;restore interrupt 8h vector
- int 21h
- lds dx,es:[int9h]
- mov ax,2509h ;restore interrupt 9h vector
- int 21h
- pop ds ;restore DS
- assume ds:code
- ;
- ;Release the memory occupied by the program.
- ;
- mov ah,49h ;Free memory given to
- int 21h ; original program block
- jc uninstall_error ;jmp if error
- cmp es:environment_flg,0 ;See if environment still
- je uninstall1 ; owned by resident code.
- push es
- mov es,es:env_seg ;Get segment of environment
- mov ah,49h ;Deallocate environment seg
- int 21h
- pop es
- jc uninstall_error ;Jmp if error
- uninstall1:
- ;
- ;Destroy the ASCII fingerprint that identifies the code and exit.
- ;
- not word ptr es:[begin] ;destroy fingerprint
- mov dx,offset infomsg2 ;Say program removed.
- uninstall_exit:
- stc ;Set flag to end program
- pop cx
- ret ;exit
- ;
- ;The program can't be uninstalled. Point to error message and exit.
- ;
- uninstall_error:
- mov dx,offset errmsg2 ;Remove error message
- jmp short uninstall_exit
- uninstall endp
-
- ;------------------------------------------------------------------------
- ; CHECKVECTOR is called by REMOVE to compare the segment pointed to by an
- ; interrupt vector against a segment value supplied by the caller.
- ; Entry: AL - interrupt number
- ; Exit: ZF clear - segments do not match
- ; ZF set - segments match
- ;------------------------------------------------------------------------
- checkvector proc near
- push es
- pop cx
- mov ah,35h ;get vector
- int 21h
- mov ax,es ;transfer segment to AX
- cmp ax,cx ;compare
- ret
- checkvector endp
-
- ;------------------------------------------------------------------------
- ; COPYSTR Copies an ASCIIZ string
- ; Entry: SI - Ptr to source ASCIIZ string
- ; DI - Ptr to destination buffer
- ;------------------------------------------------------------------------
- copy_str proc near
- push ax
- copy_str_1:
- lodsb
- or al,al
- je copy_str_2
- stosb
- jmp short copy_str_1
- copy_str_2:
- pop ax
- ret
- copy_str endp
-
- code ends
- end begin
-